import {ScriptRender} from "../../utils/ScriptRender";
import {supportFunction} from "../../utils/supportFunction";
import {stringUtils} from "../../utils/stringUtils";
import {Loader} from "./Loader";
import {MidwayConfig} from "../midway";
import {ScriptLibraryManager} from "../managers/ScriptLibraryManager";
import jQuery from 'jquery';

class ThirdLibraryLoader {
    constructor() {
        this._loader = undefined;
        this._defMappings = {};
    }

    /**
     * 创建第三方库的加载器
     * @returns {*}
     */
    create() {
        if (this._loader === undefined) {
            this._loader = new Loader(this._getKey, this._createLoadPromise, this);
        }
        return this._loader;
    }

    _getKey(item) {
        return item.name;
    }

    _createLoadPromise(config) {
        let deferred = $.Deferred();
        return deferred.resolve().then(() => {
            return this._importStyle(config);
        }).then(() => {
            if (config.depends.length === 0) {
                return this._importJsLib(config);
            } else {
                const defList = this._getDependDef(config.depends);
                return jQuery.when.apply(this, defList).done(() => {
                    return this._importJsLib(config);
                })
            }
        });
    }

    _importJsLib(config) {
        let loadList = [];
        config.scripts.forEach((item) => {
            loadList.push({
                fn: ScriptRender.addJavascript,
                args: [item + "?release=" + config.release]
            });
        });
        if (!supportFunction.hasProp(this._defMappings, config.name)) {
            this._defMappings[config.name] = supportFunction.runSequence(loadList, "Load Javascript Library");
        }
        return this._defMappings[config.name];
    }

    _importStyle(config) {
        let loadList = [];
        config.styles.forEach((item) => {
            loadList.push({
                fn: ScriptRender.addStyle,
                args: [item + "?release=" + config.release]
            });
        });
        return supportFunction.runSequence(loadList, "Load Style Library");
    }

    _getDependDef(deps) {
        let result = [];
        deps.forEach(dep => {
            if (supportFunction.hasProp(this._defMappings, dep.name)) {
                result.push(this._defMappings[dep.name]);
            }
        });
        return result;
    }
}

const JsLibLoader = (function () {
    let instance;
    return {
        name: "ThirdLibraryLoader",
        getInstance: () => {
            if (instance === undefined) {
                instance = new ThirdLibraryLoader();
            }
            return instance
        },
        findDependScript: (config, loadLibs, preLoad = false) => {
            if (config.depends.length === 0) {
                if (!supportFunction.hasProp(loadLibs, config.name)) {
                    JsLibLoader.addToLoadLibs(config, loadLibs, config.autoLoad, preLoad);
                }
            } else {
                config.depends.forEach(depend => {
                    if (ScriptLibraryManager.getInstance().exists(depend.name)) {
                        //如果已经添加过
                        let tConfig = ScriptLibraryManager.getInstance().get(depend.name);
                        if (tConfig.depends.length > 0) {
                            JsLibLoader.findDependScript(tConfig, loadLibs);
                        } else {
                            JsLibLoader.addToLoadLibs(tConfig, loadLibs, config.autoLoad, preLoad);
                        }
                    } else {
                        //如果没有被添加过
                        let dependScript = ScriptLibraryManager.getInstance().ScriptSettings.find(item => {
                            return item.name === depend.name;
                        });
                        if (!dependScript) {
                            //未能找到依赖脚本库的配置
                            console.warn('Failed to find the configuration of ' + depend.name + ' on which ' + config.name + ' depends');
                        } else {
                            ScriptLibraryManager.getInstance().add(dependScript.name, {
                                name: dependScript.name,
                                autoLoad: dependScript.autoLoad,
                                version: dependScript.version,
                                styles: dependScript.css || [],
                                scripts: dependScript.script || [],
                                depends: dependScript.dependencies || [],
                                loaded: false
                            });
                            let tConfig = ScriptLibraryManager.getInstance().get(dependScript.name);
                            if (tConfig.depends.length > 0) {
                                JsLibLoader.findDependScript(tConfig, loadLibs);
                            } else {
                                JsLibLoader.addToLoadLibs(tConfig, loadLibs, config.autoLoad, preLoad);
                            }
                        }
                    }
                });
                JsLibLoader.addToLoadLibs(config, loadLibs, config.autoLoad, preLoad);
            }
        },
        addToLoadLibs: (config, loadLibs, autoLoad, preLoad) => {
            if (config.loaded === true) {
                return;
            }
            const index = loadLibs.findIndex(item => {
                return item.name === config.name
            });
            if (index === -1) {
                if ((preLoad === true && autoLoad === 'true') || (preLoad === false)) {
                    loadLibs.push(config);
                }
            }

        }
    }
})();

export {JsLibLoader};